package com.hefan.live.service;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.cat.common.entity.ResultBean;
import com.cat.common.meta.ResultCode;
import com.hefan.common.ons.TopicRegistry;
import com.hefan.common.ons.bean.Message;
import com.hefan.common.ons.service.ONSProducer;
import com.hefan.common.util.DynamicProperties;
import com.hefan.common.util.MapUtils;
import com.hefan.live.bean.LiveRoomPersonVo;
import com.hefan.live.bean.LivingRoomInfoVo;
import com.hefan.live.itf.LiveImOptService;
import com.hefan.live.itf.LivingRedisOptService;
import com.hefan.live.itf.RoomEnterExitOptService;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * 用户进出直播间操作
 * 
 * @author kevin_zhang
 *
 */
@Component("roomEnterExitOptService")
public class RoomEnterExitOptServiceImpl implements RoomEnterExitOptService {
	public Logger logger = LoggerFactory.getLogger(RoomEnterExitOptServiceImpl.class);

	@Resource
	LiveImOptService liveImOptService;
	@Resource
	LivingRedisOptService livingRedisOptService;
	@Resource
	ONSProducer onsProducer;

	/**
	 * 检查用户能否进入直播间
	 */
	@SuppressWarnings({ "rawtypes", "unchecked", "unused" })
	@Override
	public List enterLiveRoomCheck(String userId) {
		List resultList = new ArrayList<>();
		try {
			if (livingRedisOptService.isExistsUserEnterLivingInfo_Hash(userId)) {
				logger.info("用户已进入其他直播间");
				try {
					String mapStr = livingRedisOptService.getUserEnterLivingInfo_Hash(userId);
					logger.info("用户已进入其他直播间：" + mapStr);
					Map map = JSON.parseObject(mapStr, Map.class);
					resultList.add(map);

					logger.info("执行离开指定的直播间");
					String _authId = MapUtils.getStrValue(map, "authId", "");// 主播id
					String _userId = MapUtils.getStrValue(map, "userId", "");// 进入直播间用户id
					int _chatRoomId = MapUtils.getIntValue(map, "chatRoomId", -1);// 进入直播间对应聊天室id
					String _liveUuid = MapUtils.getStrValue(map, "liveUuid", "");// 直播间UUID
					String _deviceToken = MapUtils.getStrValue(map, "deviceToken", "");// 设备deviceToken
					// 执行离开指定的直播间
					exitRoom(_userId, _chatRoomId, _liveUuid, _authId);
				} catch (Exception e) {
					e.printStackTrace();
					logger.error("用户进入其他直播间信息获取失败", e);
				}
			} else {
				logger.info("用户未进入任何一个直播间");
			}
		} catch (Exception e) {
			e.printStackTrace();
			logger.error("用户进入其他直播间检查操作失败", e);
		}
		return resultList;
	}

	/**
	 * 用户进入直播间
	 */
	@SuppressWarnings({ "rawtypes", "unchecked", "static-access" })
	@Override
	public ResultBean enterRoom(LiveRoomPersonVo user, String liveUuid, int chatRoomId, String authId,
			String deviceToken) {
		ResultBean resultBean = new ResultBean();
		resultBean.setCode(ResultCode.UNSUCCESS.get_code());
		resultBean.setMsg(ResultCode.UNSUCCESS.getMsg());
		try {
			// 添加check用户的hash值
			Map map = new HashMap();
			map.put("userId", user.getUserId());// 进入直播间用户id
			map.put("deviceToken", deviceToken);// 设备deviceToken
			map.put("authId", authId);// 主播id
			map.put("chatRoomId", chatRoomId);// 进入直播间对应聊天室id
			map.put("liveUuid", liveUuid);// 直播间UUID
			String valueCheck = JSON.toJSONString(map);
			logger.info("用户已进入直播间：" + valueCheck);
			long lCheck = livingRedisOptService.addUserEnterLivingInfo_Hash(user.getUserId(), valueCheck);
			logger.info("添加check用户的hash值 结果：" + lCheck + " valueCheck=" + valueCheck);

			// 添加用户到直播间用户列表
			String livePersonStr = JSON.toJSONString(user);
			long lRoom = livingRedisOptService.addLivingUserInfo_Hash(authId, user.getUserId(), livePersonStr);
			logger.info("添加用户到直播间用户列表 结果：" + lRoom + " livePersonStr=" + livePersonStr);

			// 添加用户到直播间用户排序列表
			if (lRoom == 1) {
				long lSort = livingRedisOptService.addLivingUserInfo_SortedSet(authId,
						user.getSortScore(user.getUserType(), user.getUserLevel()), user.getUserId());
				logger.info("添加用户到直播间用户排序列表 结果：" + lSort);
				if (lSort == 1) {
					resultBean.setCode(ResultCode.SUCCESS.get_code());
					resultBean.setMsg(ResultCode.SUCCESS.getMsg());
				}
				logger.info("用户进入直播间成功");
			}else {
				logger.info("用户进入直播间失败，用户列表信息存储失败");
			}
		} catch (Exception e) {
			e.printStackTrace();
			logger.error("观众进入直播间，操作redis失败", e);
			resultBean.setCode(ResultCode.UNSUCCESS.get_code());
			resultBean.setMsg(ResultCode.UNSUCCESS.getMsg());
		}
		return resultBean;
	}

	/**
	 * 用户进入直播间队列消息发送
	 * 
	 * @param anchId
	 * @param chatRoomId
	 * @param liveUuid
	 * @param userId
	 * @param userType
	 * @param userLevel
	 * @param nickName
	 * @param headImg
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	@Override
	public void sendEnterRoomMsgQueue(String anchId, int chatRoomId, String liveUuid, String userId, int userType,
									  int userLevel, String nickName, String headImg) {
		try {
			// 更新直播间首页缓存
			String infoRedis = livingRedisOptService.getLivingHomePageUserListInfo(liveUuid);
			logger.info("获取其它直播间首页用户列表：" + infoRedis);
			List<Map> oUserList = StringUtils.isNotBlank(infoRedis) ? JSON.parseObject(infoRedis, List.class)
					: new ArrayList<>();
			if (oUserList.size() == 20) {
				Map itemMap = oUserList.get(oUserList.size() - 1);
				LiveRoomPersonVo item = JSON.parseObject((JSON.toJSONString(itemMap)), LiveRoomPersonVo.class);
				if (LiveRoomPersonVo.getSortScore(item.getUserType(), item.getUserLevel()) < LiveRoomPersonVo
						.getSortScore(userType, userLevel)) {
					logger.info("用户符合进入首页规则");
					// 更新直播间首页用户列表
					List userList = getOnlineUserlist(anchId, 1, 20);
					livingRedisOptService.addLivingHomePageUserListInfo(liveUuid, JSON.toJSONString(userList));
				}
			} else {
				logger.info("用户符合进入首页规则");
				// 更新直播间首页用户列表
				List userList = getOnlineUserlist(anchId, 1, 20);
				livingRedisOptService.addLivingHomePageUserListInfo(liveUuid, JSON.toJSONString(userList));
			}

			try {
				String nameStr = nickName;
				if(StringUtils.isNotBlank(nickName)) {
					nameStr = nickName.replace("\n", "\\n")
							.replace("\r", "\\r")
							.replace("\'", "\\'")
							.replace("\"", "\\\"")
							.replace("\t", "\\t")
							.replace("\b", "\\b")
							.replace("\f", "\\f");
				}
				// 进入直播间队列消息发送
				Map paramMap = new HashMap<>();
				paramMap.put("userId", userId);// 进入直播间用户id
				paramMap.put("nickName", nameStr);// 进入直播间用户昵称
				paramMap.put("headImg", headImg);// 进入直播间用户头像
				paramMap.put("userLevel", userLevel);// 进入直播间用户等级
				paramMap.put("userType", userType);// 进入直播间用户类型
				paramMap.put("authoruserId", anchId);// 主播id
				paramMap.put("chatRoomId", chatRoomId);// 进入直播间对应聊天室id
				paramMap.put("liveUuid", liveUuid);// 直播间UUID

				Message message = new Message();
				message.put("joinLiveRoomVo", JSON.toJSONString(paramMap));
				message.setTopic(TopicRegistry.HEFAN_LIVE_ENTER);
				message.setTag(DynamicProperties.getString("ons.env"));
				onsProducer.sendMsg(message);
			} catch (Exception e) {
				e.printStackTrace();
				logger.error("进入直播间队列消息发送失败", e);
			}
		} catch (Exception e) {
			e.printStackTrace();
			logger.error("进入直播间队列消息发送处理失败", e);
		}
	}

	/**
	 * 用户离开直播间
	 */
	@SuppressWarnings("rawtypes")
	@Override
	public ResultBean exitRoom(String userId, int chatRoomId, String liveUuid, String authId) {
		ResultBean resultBean = new ResultBean();
		resultBean.setCode(ResultCode.UNSUCCESS.get_code());
		resultBean.setMsg(ResultCode.UNSUCCESS.getMsg());
		try {
			// 删除直播间指定用户信息
			long lRoom = livingRedisOptService.delLivingUserInfo_Hash(authId, userId);
			logger.info("删除直播间用户列表信息 结果：" + lRoom);

			// 删除直播间用户排序列表信息
			long lSort = livingRedisOptService.delLivingUserInfo_SortedSet(authId, userId);
			if (lSort == 1) {
				resultBean.setCode(ResultCode.SUCCESS.get_code());
				resultBean.setMsg(ResultCode.SUCCESS.getMsg());
			}
			logger.info("删除直播间用户排序列表信息 结果：" + lSort);

			// 删除check用户的hash值
			long lCheck = livingRedisOptService.delUserEnterLivingInfo_Hash(userId);
			logger.info("删除check用户的hash值 结果：" + lCheck);

			logger.info("用户离开直播间成功");
		} catch (Exception e) {
			e.printStackTrace();
			logger.error("用户离开直播间，操作redis失败", e);
			resultBean.setCode(ResultCode.UNSUCCESS.get_code());
			resultBean.setMsg(ResultCode.UNSUCCESS.getMsg());
		}
		return resultBean;
	}

	/**
	 * 用户离开直播间队列消息发送
	 * 
	 * @param authoruserId
	 * @param chatRoomId
	 * @param liveUuid
	 * @param userId
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	@Override
	public void sendExitRoomMsgQueue(String authoruserId, int chatRoomId, String liveUuid, String userId){
		try {
			// 更新直播间首页缓存
			String infoRedis = livingRedisOptService.getLivingHomePageUserListInfo(liveUuid);
			logger.info("获取其它直播间首页用户列表：" + infoRedis);
			List<Map> oUserList = StringUtils.isNotBlank(infoRedis) ? JSON.parseObject(infoRedis, List.class)
					: new ArrayList<>();
			if (oUserList.size() > 0) {
				for (Map itemMap : oUserList) {
					LiveRoomPersonVo item = JSON.parseObject((JSON.toJSONString(itemMap)), LiveRoomPersonVo.class);
					if (item.getUserId().equals(userId)) {
						logger.info("用户符合离开首页规则");
						// 更新直播间首页用户列表
						List userList = getOnlineUserlist(authoruserId, 1, 20);
						livingRedisOptService.addLivingHomePageUserListInfo(liveUuid, JSON.toJSONString(userList));

						try {
							// 离开直播间队列消息发送
							Map paramMap = new HashMap<>();
							paramMap.put("userId", userId);// 进入直播间用户id
							paramMap.put("authoruserId", authoruserId);// 主播id
							paramMap.put("chatRoomId", chatRoomId);// 进入直播间对应聊天室id
							paramMap.put("liveUuid", liveUuid);// 直播间UUID

							Message message = new Message();
							message.put("leftLiveRoomVo", JSON.toJSONString(paramMap));
							message.setTopic(TopicRegistry.HEFAN_LIVE_ENTER);
							message.setTag(DynamicProperties.getString("ons.env"));
							onsProducer.sendMsg(message);
						} catch (Exception e) {
							e.printStackTrace();
							logger.error("离开直播间队列消息发送失败", e);
						}
						return;
					}
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
			logger.error("离开直播间队列消息发送处理失败", e);
		}
	}

	/**
	 * 获取直播间实际观看人数
	 */
	@Override
	public long getLiveRoomPeoleCount(String authId) {
		long peopleCount = 0l;
		try {
			peopleCount = livingRedisOptService.getLivingUserCount_SortedSet(authId);
			logger.info("获取主播：" + authId + " 直播间的在线观看人数：" + peopleCount);
		} catch (Exception e) {
			e.printStackTrace();
			logger.error("获取主播：" + authId + " 直播间的在线观看人数出错", e);
		}
		return peopleCount;
	}

	/**
	 * 获取用户列表分页信息
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	@Override
	public List getOnlineUserlist(String authId, int pageNum, int pageSize) {
		List pageList = new ArrayList<>();
		try {
			pageList.addAll(livingRedisOptService.getLivingUserList_SortedSet(authId, pageNum, pageSize));
			logger.info("获取主播：" + authId + " 直播间的用户列表：" + pageList);
		} catch (Exception e) {
			e.printStackTrace();
			logger.error("获取主播：" + authId + " 直播间的用户列表出错", e);
		}
		return pageList;
	}

	/**
	 * 获取所有可显示的正在直播的直播间列表信息
	 */
	@SuppressWarnings("rawtypes")
	@Override
	public List<LivingRoomInfoVo> getAllLivingRoomInfoList() {
		return getLivingRoomInfoList(0);
	}

	/**
	 * 获取所有正在直播的VIP直播间列表信息
	 */
	@SuppressWarnings("rawtypes")
	@Override
	public List<LivingRoomInfoVo> getALLVIPLivingRoomInfoList() {
		return getLivingRoomInfoList(1);
	}

	/**
	 * 获取所有正在直播的直播间列表信息
	 */
	@SuppressWarnings("rawtypes")
	@Override
	public List<LivingRoomInfoVo> getALLMonitorLivingRoomInfoList() {
		return getLivingRoomInfoList(2);
	}

	/**
	 * 获取直播列表
	 * @param disType：0:APP端显示的直播列表  1:PC的直播列表  2:监控的直播列表
	 * @return
	 */
	private List<LivingRoomInfoVo> getLivingRoomInfoList(int disType) {
		List<LivingRoomInfoVo> livingRoomList = new ArrayList<LivingRoomInfoVo>();
		Map<String, String> livingMapList = new HashMap<>();
		try {
			livingMapList = livingRedisOptService.getAllLivingInfo_Hash();
			if (!MapUtils.isEmpty(livingMapList)) {
				Iterator iterator = livingMapList.values().iterator();
				while (iterator.hasNext()) {
					String val = (String) iterator.next();
					if (StringUtils.isNotBlank(val)) {
						try {
							logger.info("直播间信息解析：" + val);
							LivingRoomInfoVo livingInfo = JSON.parseObject(val, LivingRoomInfoVo.class);
							if (disType == 0) {
								//APP端显示的直播列表
								if (livingInfo.getIsShow() == 1) {
									livingInfo.setPushUrls("");
									livingInfo.setRotate(0);
									livingInfo.setDoubleSrc(0);
									livingRoomList.add(livingInfo);
								}
							} else if (disType == 1) {
								//1:PC的直播列表
								if (livingInfo.getIsVipLive() == 1)
									livingRoomList.add(livingInfo);
							} else if (disType == 2) {
								//2:所有的直播列表
								livingRoomList.add(livingInfo);
							}
						} catch (Exception e) {
							e.printStackTrace();
							logger.error("直播间信息解析出错", e);
						}
					}
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
			logger.error("获取所有正在直播的直播间列表信息出错", e);
		}
		return livingRoomList;
	}

	/**
	 * 获取指定直播间信息
	 */
	@Override
	public LivingRoomInfoVo getLivingRoomInfoByAuthId(String authId) {
		LivingRoomInfoVo livingInfo = null;
		try {
			String livingInfoStr = livingRedisOptService.getLivingInfo_Hash(authId);
			logger.info("获取指定的正在直播的直播间信息:" + livingInfoStr);
			if (StringUtils.isNotBlank(livingInfoStr))
				livingInfo = JSON.parseObject(livingInfoStr, LivingRoomInfoVo.class);
		} catch (Exception e) {
			e.printStackTrace();
			logger.error("获取指定的正在直播的直播间信息出错", e);
		}
		return livingInfo;
	}

	/**
	 * 更新指定直播间信息
	 */
	@Override
	public ResultBean setLivingRoomInfo(LivingRoomInfoVo livingRoomInfoVo) {
		ResultBean resultBean = new ResultBean(ResultCode.SUCCESS);
		try {
			String livingInfoStr = livingRedisOptService.getLivingInfo_Hash(livingRoomInfoVo.getUserId());
			logger.info("获取指定的正在直播的直播间信息:" + livingInfoStr);
			if (StringUtils.isNotBlank(livingInfoStr))
				livingRedisOptService.addLivingInfo_Hash(livingRoomInfoVo.getUserId(), JSON.toJSONString(livingRoomInfoVo));
		} catch (Exception e) {
			e.printStackTrace();
			logger.info("设置指定主播间出错");
		}
		return resultBean;
	}

	/**
	 * 发送更新直播间用户列表消息
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	@Override
	public ResultBean sendUpdateUserListIM(int chatRoomId, String liveUuid, String authoruserId) {
		ResultBean resultBean = new ResultBean(ResultCode.SUCCESS);
		try {
			logger.info("用户进出直播间－－获取要推送的直播间用户列表数据");
			String infoRedis = livingRedisOptService.getLivingHomePageUserListInfo(liveUuid);
			List imList = new ArrayList<>();
			if (StringUtils.isNotBlank(infoRedis)) {
				List<Map> rList = JSON.parseObject(infoRedis, List.class);
				for (int i = 0; i < rList.size(); i++) {
					imList.add(rList.get(i));
				}
			}
			Map map = new HashMap();
			map.put("membersList", imList);

			logger.info("用户进出直播间－－发送用户列表更新消息");
			resultBean = liveImOptService.updateUserListIm(chatRoomId, liveUuid, authoruserId,
					JSONObject.toJSONString(map));
			if (resultBean.getCode() == ResultCode.SUCCESS.get_code()) {
				logger.info("用户进出直播间－－直播间" + chatRoomId + "_" + liveUuid + "更新用户列表 " + imList.size() + " 个 IM消息发送成功！");
			} else {
				logger.info("用户进出直播间－－直播间" + chatRoomId + "_" + liveUuid + "更新用户列表IM消息发送失败！");
			}
		} catch (Exception e) {
			e.printStackTrace();
			logger.info("用户进出直播间－－直播间更新用户列表消息处理出错");
		}
		return resultBean;
	}

	/**
	 * 开关播清除数据
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	@Override
	public void endLiveClear(String authId) {
		try {
			// 删除指定直播间所有用户列表信息
			long lRoom = livingRedisOptService.delAllLivingUserInfo_Hash(authId);
			logger.info("删除直播间用户列表信息 结果：" + lRoom);

			// 删除指定直播间所有用户排序列表信息
			long lSort = livingRedisOptService.delAllLivingUserInfo_SortedSet(authId);
			logger.info("删除直播间用户排序列表信息 结果：" + lSort);

			// 获取指定直播间内所有机器人ID
			List listAllRobot = livingRedisOptService.getLivingRoomRobotList(authId);
			// 归还机器人到全局机器人缓存中
			if (null != listAllRobot && listAllRobot.size() > 0) {
			// 批量归还机器人
				livingRedisOptService.returnRobotIdsToAll(authId, listAllRobot);
			// 清除直播间内机器人ID
				livingRedisOptService.removeAllRoomRobot(authId);
			} else {
				logger.info("{}直播间内未查找到机器人",authId);
			}

		} catch (Exception e) {
			e.printStackTrace();
			logger.error("开关播时清除直播间观众，操作redis失败", e);
		}
	}
}
